package com.ezandroid.util;

import android.text.TextUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * Util
 *
 * @author like
 * @date 2016-05-23
 */
public class Util {

    public static Long parseLong(String string, long defaultValue) {
        if (TextUtils.isEmpty(string)) return defaultValue;
        try {
            return Long.parseLong(string);
        } catch (NumberFormatException e) {
            LogUtil.w(e);
        }

        return defaultValue;
    }

    public static Integer parseInt(String string, int defaultValue) {
        if (TextUtils.isEmpty(string)) return defaultValue;
        try {
            return Integer.parseInt(string);
        } catch (NumberFormatException e) {
            LogUtil.w(e);
        }

        return defaultValue;
    }

    public static Double parseDouble(String string, double defaultValue) {
        if (TextUtils.isEmpty(string)) return defaultValue;
        try {
            return Double.parseDouble(string);
        } catch (NumberFormatException e) {
            LogUtil.w(e);
        }

        return defaultValue;
    }

    public static Float parseFloat(String string, float defaultValue) {
        if (TextUtils.isEmpty(string)) return defaultValue;
        try {
            return Float.parseFloat(string);
        } catch (NumberFormatException e) {
            LogUtil.w(e);
        }

        return defaultValue;
    }

    public static String encode(String str) {
        try {
            if (!TextUtils.isEmpty(str)) {
                return URLEncoder.encode(str, "UTF-8");
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }

    public static String decode(String str) {
        try {
            if (!TextUtils.isEmpty(str)) {
                return URLDecoder.decode(str, "UTF-8");
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }

    // 11位手机号
    private static Pattern PHONE_PATTERN = Pattern.compile("^1\\d{10}$");

    // 4位验证码
    private static Pattern CODE_PATTERN = Pattern.compile("^\\d{4}$");

    public static boolean checkCode(String checkString) {
        return !TextUtils.isEmpty(checkString) && CODE_PATTERN.matcher(checkString).find();
    }

    public static boolean checkPhone(String checkString) {
        return !TextUtils.isEmpty(checkString) && PHONE_PATTERN.matcher(checkString).find();
    }

    public static String encodeUrl(String url, Map<String, String> params) {
        String urlStr = url;
        if (!urlStr.contains("?")) {
            urlStr += '?';
        }
        urlStr += encodeParams(params);
        return urlStr;
    }

    public static String encodeParams(Map<String, String> params) {
        StringBuilder encodedParams = new StringBuilder();
        String paramsEncoding = "UTF-8";
        try {
            Set<Map.Entry<String, String>> entrySet = params.entrySet();
            int size = entrySet.size();
            int index = 0;
            for (Map.Entry<String, String> entry : entrySet) {
                encodedParams.append(URLEncoder.encode(entry.getKey(), paramsEncoding));
                encodedParams.append('=');
                encodedParams.append(URLEncoder.encode(entry.getValue(), paramsEncoding));
                if (++index < size) {
                    encodedParams.append('&');
                }
            }
            return encodedParams.toString();
        } catch (UnsupportedEncodingException uee) {
            throw new RuntimeException("Encoding not supported: " + paramsEncoding, uee);
        }
    }

    /**
     * 加密签名
     *
     * @param strSrc  要加密的字符串
     * @param encName 加密类型
     * @return 签名值
     */
    public static String encrypt(String strSrc, String encName) {
        String sign = "";
        try {
            MessageDigest md = MessageDigest.getInstance(encName);
            sign = byte2hex(md.digest(strSrc.getBytes("utf-8")));
        } catch (Exception e) {
            // ignore
        }

        return sign;
    }

    /**
     * 二行制转字符串
     *
     * @param bytes
     */
    private static String byte2hex(byte[] bytes) {
        StringBuilder builder = new StringBuilder();
        String temp;
        for (byte b : bytes) {
            temp = (Integer.toHexString(b & 0XFF));
            if (temp.length() == 1) builder.append("0").append(temp);
            else builder.append(temp);
        }
        return builder.toString().toLowerCase(Locale.CHINA);
    }

    /**
     * 对参数进行排序并组合MD5签名
     *
     * @param map 参数map
     * @param key 特殊字符串
     * @return
     */
    public static String signature(Map<String, String> map, String key) {
        if (null == map || map.isEmpty()) return "";

        List<Map.Entry<String, String>> list = new ArrayList<>(map.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> lhs, Map.Entry<String, String> rhs) {
                return lhs.getKey().compareTo(rhs.getKey());
            }
        });

        final StringBuilder builder = new StringBuilder();
        int size = list.size();
        HashMap.Entry<String, String> entryFirst = list.get(0);
        builder.append(encode(entryFirst.getKey()));
        builder.append("=");
        builder.append(encode(entryFirst.getValue()));
        for (int i = 1; i < size; i++) {
            HashMap.Entry<String, String> entry = list.get(i);
            builder.append("&");
            builder.append(encode(entry.getKey()));
            builder.append("=");
            builder.append(encode(entry.getValue()));
        }
        builder.append(".");
        builder.append(key);

//        String source = builder.toString();
//        String sign = Util.encrypt(builder.toString(), "MD5");
//        LogUtil.d("Request", "Params signature:\nSource: " + source + "\n" + "MD5: " + sign);
        return Util.encrypt(builder.toString(), "MD5");
    }
}
